
Skt.Element = L.Class.extend({

	includes : L.Mixin.Events,
	
	events: ['change'],

	options : {},

	initialize : function(attrs, options) {
		L.setOptions(this, options);
		this.deserialize(attrs || {});
		this._fireEvents = true;
		/* set id */
		this.id = attrs.id || Skt.sketchpad.nextId();
	},

	onAdd : function(canvas) {
		this._canvas = canvas;
		this.draw();
	},

	addTo : function(canvas) {
		canvas.addElement(this);
		return this;
	},

	onRemove : function(canvas) {
		this.erase();
		this._canvas = null;
	},

	onUpdate : function() {
		this.erase();
		this.draw();
		return this;
	},

	serialize : function() {
		var attrs = {};
		L.Util.extend(attrs, this._attrs);
		if (typeof attrs.path == "object") {
			attrs.path = this.svg_path_to_string(attrs.path);
		}
		return attrs;
	},

	deserialize : function(attrs) {
		this._attrs = attrs;
		if (this._canvas) {
			this.draw();
		}
	},

	attr : function() {
		if (!this._element) {
			var args = Array.prototype.slice.call(arguments);
			this.deserialize(args[0]);
			console.log("[warning]attr() aun no esta implementada para ser llamada antes de ser agrega a un canvas, argumento fue deserializado");
			return;
		}
		var resp = this._element.attr.apply(this._element, arguments);
		var attrs = this._element.attr();
		attrs.type = this._attrs.type;
		attrs.logical_type = this._attrs.logical_type;
		attrs.path = this._attrs.path;
		attrs.layer = this._attrs.layer;
		attrs.id = this._attrs.id;
		attrs['stroke-width'] = this._attrs['stroke-width'];
		if (attrs.logical_type == "text") {
			attrs.box_width = this._attrs.box_width;
			attrs.box_height = this._attrs.box_height;
		}
		this._attrs = attrs;
		
		if (this._fireEvents) 
			this.fire('change', this);
		
		return resp != this._element ? resp : this;
	},

	noEventsAttr : function() {
		this._fireEvents = false;
		var resp = this.attr.apply(this, arguments);
		this._fireEvents = true;
		return resp != this._element ? resp : this;
	},

	draw : function() {
		var type = this._attrs.type;
		var raphael = this._canvas.getRaphael();

		// create a Raphael Element
		this._element = raphael[type]();
		this._element.id = this._attrs.id;
		this._element.attr(this._attrs);
		this._element.data('elementId', this._attrs.id);
	},

	erase : function() {
		if (this._element) {
			this._element.remove();
			this._element = null;
		}
	},

	scale : function(scale) {
		// no se guarda la propiedad escalada
		var strokeWidth = this._attrs["stroke-width"] * scale;
		this._element.attr("stroke-width", strokeWidth);
	},

	getRaphaelElement : function() {
		if (this._border)
			return [ this._element, this._border ];
		return [ this._element ];
	},
	
	bindEvents : function() {
		var self = this;
	},

	unbindEvents : function() { },

	intersectWithBox : function(box) {
		var elbox = this._element.getBBox();
		var inter = Raphael.isBBoxIntersect(elbox, box);
		return inter;
	},

	intersectWithPath : function(path) {
		var inter = Raphael.pathIntersection(this._element.attrs.path, path.attrs.path);
		return inter.length > 0;
	},

	drawBorder : function() {
		this.removeBorder();
		this._border = this._element.glow({
			color : this._element.attr('stroke')
		});
	},

	removeBorder : function() {
		if (this._border) {
			this._border.remove();
			this._border = null;
		}
	},

	move : function(dx, dy) {
		this._element.transform('t' + dx + ',' + dy + '...');
		if (this._fireEvents) {
			this.fire('change', this);
		}
	},

	rotable : function() {
		var logical_type = this._attrs.logical_type;
		return true;
	},

	scalable : function() {
		var logical_type = this._attrs.logical_type;
		return true;
	},

	/*
	 *  // Create a deep copy of strokes if // the sketch is scaled, and
	 * alter the // stroke-width property of the copy var _stroke =
	 * stroke; if(this._scale != 1){ _stroke = jQuery.extend(true, {},
	 * stroke); _stroke["stroke-width"] *= this._scale; }
	 * 
	 */
	svg_path_to_string : function(path) {
		var str = "";
		for (var i = 0, n = path.length; i < n; i++) {
			var point = path[i];
			str += point[0] + point.slice(1).join(',');
		}
		return str;
	},

});
